"""
It needs empty GameState
It can change phase from WelcomeScreen to
1) Settings phase
2) StartGame phase
3) Rules Phase
"""

from model.gamestate import GameState, Phase

from ui.hat_widget import HatWidget
import urllib2
import socket
import threading


class TimeoutError(RuntimeError):
    pass


class AsyncCall(object):
    def __init__(self, fnc, callback=None):
        self.Callable = fnc
        self.Callback = callback

    def __call__(self, *args, **kwargs):
        self.Thread = threading.Thread(target=self.run,
                                       name=self.Callable.__name__,
                                       args=args, kwargs=kwargs)
        self.Thread.start()
        return self

    def wait(self, timeout=None):
        self.Thread.join(timeout)
        if self.Thread.isAlive():
            raise TimeoutError()
        else:
            return self.Result

    def run(self, *args, **kwargs):
        self.Result = self.Callable(*args, **kwargs)
        if self.Callback:
            self.Callback(self.Result)


class AsyncMethod(object):
    def __init__(self, fnc, callback=None):
        self.Callable = fnc
        self.Callback = callback

    def __call__(self, *args, **kwargs):
        return AsyncCall(self.Callable, self.Callback)(*args, **kwargs)


def Async(fnc=None, callback=None):
    if fnc is None:
        def AddAsyncCallback(fnc):
            return AsyncMethod(fnc, callback)
        return AddAsyncCallback
    else:
        return AsyncMethod(fnc, callback)


@Async
def CheckServerConnection(scrn, url):
        try:
            urllib2.urlopen(url, timeout=1)
            scrn.join_button.enabled = True
            scrn.load_button.enabled = True
        except:
            return False
        return True


class WelcomeScreen(HatWidget):
    def __init__(self, gamestate, presenter, **kwargs):
        """ Construct Welcome screen
            Args:
            gamestate: (GameState)
            mainview: (Presenter) main view presenter
        """
        self.presenter = presenter
        self.presenter.game_state = GameState(None, None, None, Phase.WELCOME,
                                              None, None, None)
        gamestate.shall_change = True
        self.presenter.game_state.shall_change = True
        super(WelcomeScreen, self).__init__(**kwargs)
        self.join_button.enabled = False
        self.load_button.enabled = False
        CheckServerConnection(self, self.presenter.settings.game.server_name)
        self.count_dicts()

    def count_dicts(self):
        dicts = self.presenter.settings.dictionaries.enabled_dictionaries
        for key in dicts:
            if dicts[key]:
                self.quick_game_button.enabled = True
                return

        self.quick_game_button.enabled = False

    def start_game(self):
        """ changes phase to Game Settings
            call on release 'Create Game' button
        """
        self.presenter.change_phase(Phase.GAME_CONFIG)

    def quick_game(self):
        self.presenter.change_phase(Phase.QUICK_GAME_SETTINGS)

    def open_rules(self):
        """changes phase to RULES phase
        call on release 'Rules' button
        """
        self.presenter.change_phase(Phase.RULES)

    def load_game(self):
        """changes phase to LOAD_GAME phase
        call on release 'load game' button
        """
        self.presenter.change_phase(Phase.LOAD_GAME)

    def go_back(self):
        self.presenter.request_app_close()

    def join(self):
        self.presenter.change_phase(Phase.JOIN)
